// @ts-ignore
import * as changeCase from "change-case"
import fs from "fs"
import path, { join } from "path"

interface SwaggerOperation {
  path: string
  method: string
  operation: {
    summary: string
    operationId: string
    tags: string[]
    parameters?: any[]
    requestBody?: any
    responses?: any
  }
}

interface SwaggerData {
  paths: { [path: string]: any }
  components?: {
    schemas?: { [name: string]: any }
  }
}

interface ApiGroup {
  [groupPath: string]: {
    [resourceName: string]: SwaggerOperation[]
  }
}

class TypeScriptApiGenerator {
  private outputDir: string
  private swaggerData: SwaggerData

  constructor(swaggerData: SwaggerData, outputDir: string = "api-gen") {
    this.swaggerData = swaggerData
    this.outputDir = outputDir
  }

  // 解析Swagger数据并生成TypeScript文件
  async generateTypeScriptFiles(): Promise<void> {
    const apiGroups = this.groupApisByPath()

    for (const [groupPath, resources] of Object.entries(apiGroups)) {
      for (const [resourceName, apis] of Object.entries(resources)) {
        const tsContent = this.generateTypeScriptFile(resourceName, apis)
        await this.saveTypeScriptFile(groupPath, resourceName, tsContent)
      }
    }
  }

  // 按路径分组API
  private groupApisByPath(): ApiGroup {
    const groups: ApiGroup = {}
    const paths = this.swaggerData.paths

    Object.keys(paths).forEach((path) => {
      const pathItem = paths[path]

      Object.keys(pathItem).forEach((method) => {
        if (
          ["get", "post", "put", "delete", "patch"].includes(
            method.toLowerCase()
          )
        ) {
          const operation = pathItem[method]

          // 提取分组路径和资源名称
          const { groupPath, resourceName } = this.extractPathInfo(path)

          if (!groups[groupPath]) {
            groups[groupPath] = {}
          }

          if (!groups[groupPath][resourceName]) {
            groups[groupPath][resourceName] = []
          }

          groups[groupPath][resourceName].push({
            path,
            method: method.toUpperCase(),
            operation
          })
        }
      })
    })

    return groups
  }

  // 从路径中提取分组路径和资源名称
  private extractPathInfo(path: string): {
    groupPath: string
    resourceName: string
  } {
    // 提取API前缀（admin-api, easyTrans, rpc-api, app-api等）
    const prefixMatch = path.match(/^\/(admin-api|easyTrans|rpc-api|app-api)\//)
    const apiPrefix = prefixMatch ? prefixMatch[1] : ""

    // 移除API前缀后处理剩余路径
    const cleanPath = apiPrefix ? path.replace(`/${apiPrefix}/`, "") : path
    const pathParts = cleanPath.split("/").filter((part) => part.length > 0)

    if (pathParts.length >= 2) {
      // 倒数第二层作为资源名，前面的作为分组路径
      const resourceName = pathParts[pathParts.length - 2]
      const innerGroupPath = pathParts.slice(0, -2).join("/")

      // 将API前缀添加到分组路径的最前面
      const groupPath = apiPrefix
        ? join(apiPrefix, innerGroupPath)
        : innerGroupPath
      return { groupPath, resourceName }
    }

    // 如果路径不够长，API前缀作为分组路径，最后一层作为资源名
    const resourceName = pathParts[0] || "unknown"
    return { groupPath: apiPrefix, resourceName }
  }
  // 生成单个TypeScript文件内容
  private generateTypeScriptFile(
    resourceName: string,
    apis: SwaggerOperation[]
  ): string {
    const pascalResourceName = changeCase.pascalCase(resourceName)

    // 生成导入语句
    const imports = this.generateImports()

    // 生成接口定义
    const interfaces = this.generateInterfaces(resourceName, apis)

    // 生成API函数
    const functions = this.generateApiFunctions(resourceName, apis)

    return `${imports}\n\n${interfaces}\n\n${functions}`
  }

  // 生成导入语句
  private generateImports(): string {
    return `import request from '@/config/axios'

export interface PageParam {
  pageNo: number
  pageSize: number
}`
  }

  // 生成接口定义
  private generateInterfaces(
    resourceName: string,
    apis: SwaggerOperation[]
  ): string {
    const pascalResourceName = changeCase.pascalCase(resourceName)
    const interfaces: string[] = []

    // 生成主实体接口
    const mainInterface = this.generateMainEntityInterface(resourceName, apis)
    if (mainInterface) {
      interfaces.push(mainInterface)
    }

    // 生成请求参数接口
    const requestInterfaces = this.generateRequestInterfaces(resourceName, apis)
    interfaces.push(...requestInterfaces)

    return interfaces.join("\n\n")
  }

  // 生成主实体接口
  private generateMainEntityInterface(
    resourceName: string,
    apis: SwaggerOperation[]
  ): string {
    const pascalResourceName = changeCase.pascalCase(resourceName)

    // 首先尝试从GET接口的响应中提取实体结构
    const getApi = apis.find(
      (api) =>
        api.method === "GET" &&
        api.path.includes("/get") &&
        !api.path.includes("/page")
    )

    let schema = null

    if (getApi?.operation.responses?.["200"]?.content?.["*/*"]?.schema) {
      // 从GET接口响应中提取schema
      const responseSchema = this.resolveSchema(
        getApi.operation.responses["200"].content["*/*"].schema
      )

      // 通常响应是CommonResult包装的，需要提取data字段
      if (responseSchema?.properties?.data) {
        schema = this.resolveSchema(responseSchema.properties.data)
      } else {
        schema = responseSchema
      }
    }

    // 如果GET接口没有找到合适的schema，尝试从创建/更新接口的请求体中提取
    if (!schema || !schema.properties) {
      const createOrUpdateApi = apis.find(
        (api) =>
          api.operation.operationId?.includes("create") ||
          api.operation.operationId?.includes("update")
      )

      if (createOrUpdateApi?.operation.requestBody) {
        schema = this.resolveSchema(
          createOrUpdateApi.operation.requestBody.content?.["application/json"]
            ?.schema
        )
      }
    }

    if (!schema || !schema.properties) {
      // 如果都没有找到，生成一个基本的VO接口
      return `export interface ${pascalResourceName}VO {
  id: number
  name: string
  status: number
  createTime: Date
}`
    }

    const properties = Object.keys(schema.properties)
      .map((key) => {
        const prop = schema.properties[key]
        const type = this.mapSwaggerTypeToTypeScript(prop)
        const description = prop.description
          ? `  /** ${prop.description} */\n  `
          : "  "
        return `${description}${key}: ${type}`
      })
      .join("\n")

    // 添加接口注释
    const interfaceComment = schema.description
      ? `/** ${schema.description} */\n`
      : ""

    return `${interfaceComment}export interface ${pascalResourceName}VO {
${properties}
}`
  }

  // 生成请求参数接口
  private generateRequestInterfaces(
    resourceName: string,
    apis: SwaggerOperation[]
  ): string[] {
    const pascalResourceName = changeCase.pascalCase(resourceName)
    const interfaces: string[] = []

    // 查找分页查询接口
    const pageApi = apis.find(
      (api) =>
        api.operation.operationId?.includes("Page") ||
        api.path.includes("/page")
    )

    if (pageApi) {
      const pageInterface = this.generatePageRequestInterface(
        resourceName,
        pageApi
      )
      if (pageInterface) {
        interfaces.push(pageInterface)
      }

      // 生成导出接口（通常与分页参数相同）
      interfaces.push(`export interface ${pascalResourceName}ExportReqVO {
  name?: string
  contactName?: string
  contactMobile?: string
  status?: number
  createTime?: Date[]
}`)
    }

    return interfaces
  }

  // 生成分页请求接口
  private generatePageRequestInterface(
    resourceName: string,
    pageApi: SwaggerOperation
  ): string {
    const pascalResourceName = changeCase.pascalCase(resourceName)
    const properties: string[] = []

    if (pageApi.operation.parameters) {
      pageApi.operation.parameters.forEach((param: any) => {
        if (
          param.in === "query" &&
          !["pageNo", "pageSize"].includes(param.name)
        ) {
          const type = this.mapSwaggerTypeToTypeScript(param.schema)
          const optional = param.required ? "" : "?"
          properties.push(`  ${param.name}${optional}: ${type}`)
        }
      })
    }

    return `export interface ${pascalResourceName}PageReqVO extends PageParam {
${properties.join("\n")}
}`
  }

  // 生成API函数
  private generateApiFunctions(
    resourceName: string,
    apis: SwaggerOperation[]
  ): string {
    const functions: string[] = []

    apis.forEach((api) => {
      const functionCode = this.generateApiFunction(resourceName, api)
      if (functionCode) {
        functions.push(functionCode)
      }
    })

    return functions.join("\n\n")
  }

  // 生成单个API函数
  private generateApiFunction(
    resourceName: string,
    api: SwaggerOperation
  ): string {
    const pascalResourceName = changeCase.pascalCase(resourceName)

    // 生成函数名
    const functionName = this.generateFunctionName(resourceName, api)

    // 生成参数
    const params = this.generateFunctionParams(resourceName, api)

    // 生成URL
    const url = this.generateUrl(api.path)

    // 生成请求方法
    const method = api.method.toLowerCase()

    // 生成注释
    const comment = this.generateFunctionComment(api)

    return `${comment}
export const ${functionName} = (${params}) => {
  return request.${method}({ url: '${url}'${this.generateRequestData(api)} })
}`
  }

  // 生成函数名
  private generateFunctionName(
    resourceName: string,
    api: SwaggerOperation
  ): string {
    // 从路径中提取最后两个部分
    const pathParts = api.path.split("/").filter((part) => part.length > 0)

    if (pathParts.length >= 2) {
      // 取最后两个部分：倒数第二层和最后一层
      const secondLast = pathParts[pathParts.length - 2]
      const last = pathParts[pathParts.length - 1]

      // 组合成大驼峰命名
      const combined = changeCase.pascalCase(secondLast + "-" + last)
      return changeCase.camelCase(combined)
    }

    // 如果路径不够长，使用最后一层
    const last = pathParts[pathParts.length - 1] || "unknown"
    return changeCase.camelCase(last)
  }

  // 生成函数参数
  private generateFunctionParams(
    resourceName: string,
    api: SwaggerOperation
  ): string {
    const pascalResourceName = changeCase.pascalCase(resourceName)
    const method = api.method.toLowerCase()

    // 根据HTTP方法和路径确定参数类型
    if (method === "get") {
      if (api.path.includes("/page")) {
        return `params: ${pascalResourceName}PageReqVO`
      } else if (api.path.includes("/get") || api.path.includes("/valid")) {
        return `id: number`
      } else if (
        api.path.includes("/list") ||
        api.path.includes("/simple-list")
      ) {
        return ""
      } else if (api.path.includes("/export")) {
        return `params: ${pascalResourceName}ExportReqVO`
      } else {
        return "params: any"
      }
    } else if (["post", "put"].includes(method)) {
      return `data: ${pascalResourceName}VO`
    } else if (method === "delete") {
      if (api.path.includes("/delete-list")) {
        return "ids: number[]"
      } else {
        return "id: number"
      }
    }

    return "params: any"
  }

  // 生成URL
  private generateUrl(path: string): string {
    // 移除API前缀（admin-api, app-api, rpc-api, easyTrans等）
    const prefixMatch = path.match(/^\/(admin-api|app-api|rpc-api|easyTrans)\//)
    if (prefixMatch) {
      const apiPrefix = prefixMatch[1]
      return path.replace(`/${apiPrefix}`, "")
    }
    return path
  }

  // 生成请求数据
  private generateRequestData(api: SwaggerOperation): string {
    const method = api.method.toLowerCase()

    if (method === "get") {
      if (api.path.includes("/get") || api.path.includes("/valid")) {
        return ` + '?id=' + id`
      } else if (api.path.includes("/delete-list")) {
        return `, params: { ids: ids.join(',') }`
      } else if (api.path.includes("/page") || api.path.includes("/export")) {
        return `, params`
      } else {
        return ""
      }
    } else if (["post", "put"].includes(method)) {
      return `, data`
    } else if (method === "delete") {
      if (api.path.includes("/delete-list")) {
        return `, params: { ids: ids.join(',') }`
      } else {
        return ` + '?id=' + id`
      }
    }

    return ""
  }

  // 生成函数注释
  private generateFunctionComment(api: SwaggerOperation): string {
    const summary = api.operation.summary || api.operation.operationId || ""
    return `// ${summary}`
  }

  // 解析Swagger schema引用
  private resolveSchema(schema: any): any {
    if (!schema) return null

    if (schema.$ref) {
      const refPath = schema.$ref.replace("#/", "").split("/")
      let refSchema = this.swaggerData

      for (const path of refPath) {
        if (refSchema && typeof refSchema === "object" && path in refSchema) {
          refSchema = (refSchema as any)[path]
        } else {
          return null
        }
      }

      return this.resolveSchema(refSchema)
    }

    return schema
  }

  // 映射Swagger类型到TypeScript类型
  private mapSwaggerTypeToTypeScript(schema: any): string {
    if (!schema) return "any"

    if (schema.$ref) {
      const resolved = this.resolveSchema(schema)
      if (resolved) {
        return this.mapSwaggerTypeToTypeScript(resolved)
      }
      return "any"
    }

    switch (schema.type) {
      case "string":
        if (schema.format === "date-time") {
          return "Date"
        }
        return "string"
      case "integer":
      case "number":
        return "number"
      case "boolean":
        return "boolean"
      case "array":
        if (schema.items) {
          const itemType = this.mapSwaggerTypeToTypeScript(schema.items)
          return `${itemType}[]`
        }
        return "any[]"
      case "object":
        return "any"
      default:
        return "any"
    }
  }

  // 保存TypeScript文件
  private async saveTypeScriptFile(
    groupPath: string,
    resourceName: string,
    content: string
  ): Promise<void> {
    const fileName = "index.ts"

    // 构建完整的目录路径，直接使用outputDir，不添加typescript子目录
    let dirPath = this.outputDir
    if (groupPath) {
      dirPath = path.join(dirPath, groupPath)
    }

    // 为每个资源创建单独的目录
    const resourceDir = path.join(dirPath, changeCase.camelCase(resourceName))
    const filePath = path.join(resourceDir, fileName)

    // 确保目录存在
    if (!fs.existsSync(resourceDir)) {
      fs.mkdirSync(resourceDir, { recursive: true })
    }

    fs.writeFileSync(filePath, content, "utf-8")
    console.log(`TypeScript文件已生成: ${filePath}`)
  }
}

export default TypeScriptApiGenerator
